/*
 * GetFrameFromFile.h
 *
 *  Created on: Jan 18, 2013
 *      Author: bird
 */

#ifndef GETFRAMEFROMFILE_H_
#define GETFRAMEFROMFILE_H_


#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include"../minclude/HandleException.h"
namespace Frame_from_file {
#define FLAMELENMAX (80)
#define FLAGLEN (3)
#define READBUFFER (500)
#define FLAGTPYENUM (3)
#define BUFFERSIZE (1000)
typedef unsigned char byte;

typedef unsigned char BYTE;
struct RMSTREAM_HEADER //12
{
	unsigned long lFrameType; /*I帧为x0dc，p帧为x1dc 00dc*/
	unsigned long lFrameLen:24; /*仅视频帧数据长度*/
	unsigned long lStreamExam:8; /*码流校验*/
	unsigned long lExtendLen:24; /*仅扩展数据长度*/
	unsigned long lExtendCount:8;
};
struct RMS_INFOTYPE //4
{
	unsigned long lInfoType:8;
	unsigned long lInfoLength:24;
};
struct RMFI2_VIDEOINFO //4
{
	RMS_INFOTYPE stuInfoType;
	unsigned long lWidth:12;
	unsigned long lHeight:12;
	unsigned long lFPS:8;
};
struct RMS_DATETIME  //8
{
	BYTE cYear;
	BYTE cMonth;
	BYTE cDay;
	BYTE cHour;
	BYTE cMinute;
	BYTE cSecond;
	unsigned short usMilliSecond:10;
	unsigned short usWeek:3;
	unsigned short usReserved:2;
	unsigned short usMilliValidate:1;
};
struct RMFI2_RTCTIME //16
{
	RMS_INFOTYPE stuInfoType;
	RMS_DATETIME stuRtcTime;
};
struct RMFI2_VTIME //16
{
	RMS_INFOTYPE stuInfoType;
	long long llVirtualTime;
};
struct RMFI2_LONGINFO //8
{
	unsigned char cType;
	char reserved[3];
	unsigned long lValue;
};
struct RMFI2_LONGLIST //12
{
	RMS_INFOTYPE stuInfoType;
	unsigned char cItemCount;
	char reserved[3];
	RMFI2_LONGINFO *pstuVirLongList;
};
typedef struct RMS_DATETIME RMFI_DATETIME;
typedef struct _STime
{
	short yy;
	char mm;
	char dd;
	char hh;
	char minu;
	char sec;
	short others;
	bool operator==(const _STime &para)
	{
	return ((this->yy==para.yy)&&(this->mm==para.mm)&&
			(this->dd==para.dd)&&(this->hh==para.hh)&&
			(this->minu==para.minu)&&(this->sec==para.sec))?true:false;
	}
}STime;
typedef struct _FrameFlag{  //4
	char type;
	char flag[FLAGLEN];
}FramFlag;
struct N9_NET_HEAD
{
	char   byte1;
	char   byType;
	short  ssrc;
	int    nLen;
	int    nReserve;
};

class GetFrameFromFile {
public:
	STime current_time;
	unsigned int current_frame_len;
	char current_type;
	byte* data_buffer;
	GetFrameFromFile();
	/**
	 * i_time if null means from start
	 *
	 * set the offset at the first frame
	 */
	bool inite(char* i_filename,STime* i_time,FramFlag* i_flag,int i_flag_len);
	/**
	 * true set file offset
	 * false time does not contained
	 */
	bool jump_to_require_time(STime i_time);

	virtual ~GetFrameFromFile();
	/**
	 * normal is 0
	 */
	byte* get_frame(char* o_type,int* o_len);
	/*
	 *find the dst frame and assigned time and current_frame_len
	 *if the i_dst_time is null means the first frame
	 * -1 means failed and set the offset at right position
	 */
	off_t Get_the_dst_i_pframe(STime* i_dst_time);
protected:
	/**
	 * get struct of head extendinfo  ()
	 * current offset is the head offset
	 */
	bool get_frame_property(int fd);
	 /*
	  * search dst in src return the index from 1 to len
	  */
	int CStyle_Find(char* src,int src_len,char* dst,int dst_len);
	void ReverseCStr(char*,int len);
private:
	int fd; //file descriptor

	RMSTREAM_HEADER head;
	FramFlag frameflag[FLAGTPYENUM]; //
	char Get_type(char*i_str,int i_len);
	int Read_but_not_changed_offset(int fd, void* buffer,int len)
	{
		assert(buffer!=NULL&&len>0);
		int current_offset=lseek(fd,0,SEEK_CUR);
		int readnum;
		if((readnum=read(fd,buffer,len))==len)
		{
			assert(current_offset==lseek(fd,current_offset,SEEK_SET));
			return len;
		}
		else
		{
//			PrintTrackFun();
//			CHandleException::print_get_common_exception("meet EOF!!! \n");
			assert(current_offset==lseek(fd,current_offset,SEEK_SET));
			return readnum;
		}
	}
	int Find_Head_flag(char*buffer,int len);
};
} /* namespace Frame_from_file */
#endif /* GETFRAMEFROMFILE_H_ */
